package com.fumin.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fumin.Filtter.BussinessException;
import com.fumin.pojo.*;
import com.fumin.service.*;
import com.fumin.service.impl.CapitalServiceImpl;
import com.fumin.util.QcodeUtil;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.web3j.crypto.CipherException;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.WalletUtils;


import javax.annotation.Resource;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;


/**
 * Created by Lingo on 2018/3/8.
 */
@Controller
public class CapitalController {

    private static Logger logger = Logger.getLogger(CapitalController.class);

    @Resource
    UserService userService;
    @Resource
    CapitalService capitalService;
    @Resource
    InvestmentRecordService investmentRecordService;
    @Resource
    ProjectsService projectsService;
    @Resource
    EhcacheService ehcacheService;


    /**
     *  查询用户资产
     * @param userPk
     * @return
     */
    @RequestMapping(value = "/capital/user/{userPk}", method = RequestMethod.GET)
    @ResponseBody
    public Object getCapital(@PathVariable Long userPk ,@RequestHeader("User") Long userid){
        BusinessResponse response = new BusinessResponse();
        if (userid.longValue()!=userPk.longValue()){
            response.setCode("-1");
            response.setMessage("无效的请求!");
            return response;
        }
        List<Capital> results = capitalService.selectByUserPk(userPk);
        for (Capital capital:results) {
            capital.setAmount(capitalService.getBlanceByAddr(capital.getAccount_addr()));
        }
        response.setCode("0");
        response.setMessage("success");
        response.setContent(results);
        return response;
    }

    /**
     *  根据地址查询交易记录
     * @param addr
     * @return
     */
    @RequestMapping(value = "/transaction/user/{addr}/{userPk}", method = RequestMethod.GET)
    @ResponseBody
    public Object queryTransaction(@PathVariable String addr, @PathVariable Long userPk,@RequestHeader("User") Long userid){
        BusinessResponse businessResponse = new BusinessResponse();
        if (userid.longValue()!=userPk.longValue()){
            businessResponse.setCode("-1");
            businessResponse.setMessage("无效的请求!");
            return businessResponse;
        }
        JSONArray resuelt = capitalService.getTransactionRecords(addr,userPk);
        if (resuelt==null){
            businessResponse.setContent(new JSONArray());
        }else {
            resuelt = capitalService.souredByTimestamp(resuelt);
            businessResponse.setContent(resuelt);
        }
        businessResponse.setCode("0");
        businessResponse.setMessage("success");
        return businessResponse;
    }

    /**
     *  生成钱包地址二维码
     *  目前只做ETH资产
     * @param userPk
     * @return
     */
    @RequestMapping(value = "/wallet/user/{userPk}", method = RequestMethod.GET)
    @ResponseBody
    public Object qcodeOfWallet(@PathVariable Long userPk){
        List<Capital> capitals =  capitalService.selectByUserPk(userPk);
        String addr = capitals.get(0).getAccount_addr();
        byte []  bytes = QcodeUtil.getQrcodeImg(addr);
//        HttpHeaders responseHeaders = new HttpHeaders();
//        responseHeaders.set("Content-type", "image/jpg");
//        responseHeaders.set("wallet",addr);
//        ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(
//                bytes, responseHeaders, HttpStatus.OK);
        String pic = "data:image/jpeg;base64,"+ Base64.getEncoder().encodeToString(bytes);
        BusinessResponse responseEntity = new BusinessResponse();
        responseEntity.setCode("0");
        responseEntity.setMessage("success");
        responseEntity.setContent(pic);
        return responseEntity;
    }
    /**
     *  查询充值记录
     * @param addr
     * @return
     */
    @RequestMapping(value = "/charge/user/{addr}/{userPk}", method = RequestMethod.GET)
    @ResponseBody
    public Object TransactionCharge(@PathVariable String addr, @PathVariable Long userPk,@RequestHeader("User") Long userid){
        BusinessResponse businessResponse = new BusinessResponse();
        if (userid.longValue()!=userPk.longValue()){
            businessResponse.setCode("-1");
            businessResponse.setMessage("无效的请求!");
            return businessResponse;
        }
        businessResponse.setCode("0");
        businessResponse.setMessage("success");
        businessResponse.setContent(capitalService.getTransactionChargeRecords(addr,userPk));
        return businessResponse;
    }

    /**
     *  查询退款记录
     * @param addr
     * @return
     */
    @RequestMapping(value = "/refund/user/{addr}/{userPk}", method = RequestMethod.GET)
    @ResponseBody
    public Object TransactionRefund(@PathVariable String addr, @PathVariable Long userPk,@RequestHeader("User") Long userid){
        BusinessResponse businessResponse = new BusinessResponse();
        if (userid.longValue()!=userPk.longValue()){
            businessResponse.setCode("-1");
            businessResponse.setMessage("无效的请求!");
            return businessResponse;
        }
        businessResponse.setCode("0");
        businessResponse.setMessage("success");
        businessResponse.setContent(capitalService.getTransactionRefundRecords(addr,userPk));
        return businessResponse;
    }


    /**
     *  项目投资接口
     * @param projectPk
     * @param userPk
     * @return
     */
    @RequestMapping(value = "/investment/project/{userPk}/{projectPk}", method = RequestMethod.POST)
    @ResponseBody
    public Object Investment(@PathVariable Long projectPk, @PathVariable Long userPk,
                             @RequestBody InvestmentRecord investmentRecord,@RequestHeader("User") Long userid){
        BusinessResponse businessResponse = new BusinessResponse();
        if (userid.longValue()!=userPk.longValue()){
            businessResponse.setCode("-1");
            businessResponse.setMessage("无效的请求!");
            return businessResponse;
        }

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        User user = userService.selectByPrimaryKey(userPk);
        Projects  projects =projectsService.selectByPrimaryKey(projectPk);
        investmentRecord.setUser_id(userPk);
        investmentRecord.setProject_id(projectPk);
        investmentRecord.setProject_name(projects.getProject_name());
        investmentRecord.setTime(simpleDateFormat.format(new Date()));
        if (user==null){
            throw  new BussinessException("-1","用户不存在!");
        }
        Capital capital=null;
        List<Capital> capitals = capitalService.selectAllColumnsByUserPk(user.getPk());
        for (Capital temp:capitals) {
            if (temp.getUnit().toUpperCase().equals("ETH")){
                capital=temp;
            }
        }
        if (capital==null){
            throw new BussinessException("-1","无ETH资产!");
        }
        String capText = ehcacheService.getIdentifyingCode(user.getMobile_phone());
        // 借用 refund_record 的字符串字段 transaction_hash 来接收短信验证码
        if (!capText.toUpperCase().equals(investmentRecord.getTransaction_hash().toUpperCase())){
            throw new BussinessException("-1","短信验证码错误！");
        }
        //用户账户余额
        Float userBalance = capitalService.getBlanceByAddr(capital.getAccount_addr());
        //如果用户账户余额 小余 1.001倍的投资金额 转账交易终止
        if (userBalance.floatValue()<(investmentRecord.getAmount().floatValue()+0.001f)){
            throw new BussinessException("-1","账户余额不足，请注意预留投资所需的矿工费用。");
        }

        if (investmentRecord.getAmount().floatValue()<1f){
            throw new BussinessException("-1","投资至少需要1个ETH！");
        }

        // 在以太坊中添加交易请求，获得交易哈希码。如果哈希码为空，那么本次投资交易失败。
        String hexValue = investmentRecordService.transaction(capital,projects,investmentRecord.getAmount().toString());
        String txHash = investmentRecordService.commitTransaction(hexValue);
        String transactionUrl = "https://api.etherscan.io/api?module=proxy&action=eth_sendRawTransaction&hex=%s&apikey=H6T8WITXFCYG189UEFV2FTNAGWZQIFWHQW";
        transactionUrl=  String.format(transactionUrl,hexValue);
        System.out.println(simpleDateFormat.format(new Date())+"\n"+user.getMobile_phone()+" 投资请求：\n "+transactionUrl+"\n"+txHash);

        if (txHash!=null){
            investmentRecord.setTransaction_hash(txHash);
            investmentRecord.setStatus(1);
            investmentRecord.setUnit("ETH");
            investmentRecordService.insertSelective(investmentRecord);
        }else {
            businessResponse.setCode("-1");
            businessResponse.setMessage("交易失败");
            return businessResponse;
        }
        businessResponse.setCode("0");
        businessResponse.setMessage("投资成功，转账需要等待区块链写入数据。请稍后");
        businessResponse.setContent(txHash);
        return businessResponse;
    }


    /**
     *  查询投资转账记录
     * @param addr
     * @return
     */
    @RequestMapping(value = "/investment/user/{addr}/{userPk}", method = RequestMethod.GET)
    @ResponseBody
    public Object TransactionInvestment(@PathVariable String addr, @PathVariable Long userPk,@RequestHeader("User") Long userid){
        BusinessResponse businessResponse = new BusinessResponse();
        if (userid.longValue()!=userPk.longValue()){
            businessResponse.setCode("-1");
            businessResponse.setMessage("无效的请求!");
            return businessResponse;
        }
        businessResponse.setCode("0");
        businessResponse.setMessage("success");
        businessResponse.setContent(capitalService.getTransactionInvestmentRecords(addr,userPk));
        return businessResponse;
    }
    /**
     *  查询投资记录
     * @return
     */
    @RequestMapping(value = "/investment/record/{addr}/{userPk}", method = RequestMethod.GET)
    @ResponseBody
    public Object InvestmentRecords(@PathVariable String addr, @PathVariable Long userPk,@RequestHeader("User") Long userid){
        BusinessResponse businessResponse = new BusinessResponse();
        if (userid.longValue()!=userPk.longValue()){
            businessResponse.setCode("-1");
            businessResponse.setMessage("无效的请求!");
            return businessResponse;
        }
        businessResponse.setCode("0");
        businessResponse.setMessage("success");
        List<InvestmentRecord> records = capitalService.getInvestmentRecords("",userPk);
//        JSONArray transactionInvestmentRecords = capitalService.getTransactionInvestmentRecords(addr,userPk);
        JSONArray jsonArray =  new JSONArray();
        for (InvestmentRecord r:
                records) {
            JSONObject temp =(JSONObject)JSONObject.toJSON(r);
            temp.put("id",String.format("%08d",temp.getLong("id")));
            Integer status = temp.getInteger("status");
            if (status==0){
                temp.put("status","付款处理中");
            }else if (status==1){
                temp.put("status","投资中");
            }else if (status==2){
                temp.put("status","等待发币");
            } else if (status==3){
                temp.put("status","退款");
            } else if (status==4){
                temp.put("status","完成'");
            }else {
                temp.put("status","失败'");
            }
//            for (int i = 0; i <transactionInvestmentRecords.size() ; i++) {
//                JSONObject tem = transactionInvestmentRecords.getJSONObject(i);
//                if (tem.getString("hash").toUpperCase().equals(r.getTransaction_hash().toUpperCase())){
//                    temp.put("time",tem.getString("timeStamp"));
//                }
//            }
            jsonArray.add(temp);
        }
        businessResponse.setContent(jsonArray);
        return businessResponse;
    }



    /**
     *  提现接口
     * @param addr
     * @return
     */
    @RequestMapping(value = "/withdraw/user/{addr}/{userPk}", method = RequestMethod.POST)
    @ResponseBody
    public Object Withdraw(@PathVariable String addr, @PathVariable Long userPk,
                           @RequestBody RefundRecord refundRecord ,@RequestHeader("User") Long userid){
        BusinessResponse businessResponse = new BusinessResponse();
        if (userid.longValue()!=userPk.longValue()){
            businessResponse.setCode("-1");
            businessResponse.setMessage("无效的请求!");
            return businessResponse;
        }
        User user = userService.selectByPrimaryKey(userPk);
        if (user==null){
            throw  new BussinessException("-1","用户不存在!");
        }
        String phone = user.getMobile_phone();
        String capText = ehcacheService.getIdentifyingCode(phone);
        // 借用 refund_record 的字符串字段 transaction_hash 来接收短信验证码
        if (!capText.toUpperCase().equals(refundRecord.getTransaction_hash().toUpperCase())){
            throw new BussinessException("-1","短信验证码错误！");
        }

        Capital capital=null;
        List<Capital> capitals = capitalService.selectAllColumnsByUserPk(user.getPk());
        for (Capital temp:capitals) {
            if (temp.getUnit().toUpperCase().equals("ETH")){
                capital=temp;
            }
        }
        if (capital==null){
            throw new BussinessException("-1","无ETH资产!");
        }
        //用户账户余额
        Float userBalance = capitalService.getBlanceByAddr(capital.getAccount_addr());
        //如果用户账户余额 小余 1.001倍的投资金额 转账交易终止
        if (userBalance.floatValue()<1.001*refundRecord.getAmount().floatValue()){
            throw new BussinessException("-1","账户余额不足，请注意预留提现所需的矿工费用。");
        }
        if (refundRecord.getAmount().floatValue()<1f){
            throw new BussinessException("-1","至少需要1个ETH!");
        }

        //调用eth接口，查询汇入地址
        String url = "http://api.etherscan.io/api?module=account&action=txlist&" +
                "address=%s" +
                "&startblock=0&endblock=99999999&sort=desc&" +
                "apikey=%s";
        url = String.format(url,capital.getAccount_addr(),"H6T8WITXFCYG189UEFV2FTNAGWZQIFWHQW");

        HttpResponse<String> response  = null;
        try {
            response = Unirest.get(url)
                    .header("cache-control", "no-cache")
                    .header("postman-token", "01e8236c-7f07-2b64-833e-0a5403afd5d9")
                    .asString();
        } catch (UnirestException e) {
            logger.error(e.getMessage());
            return null;
        }
        String body = response.getBody();
        JSONObject resuelt = JSON.parseObject(body);
        JSONArray ethResutlt = resuelt.getJSONArray("result");

        String orignalAddr = ethResutlt.getJSONObject(0).getString("from");

        String messageTemp = "http://sms.microsoco.com/sms.aspx?action=send&userid=3007&account=hybuzhi&password=123987&" +
                "mobile=%s&" +
                "content=%s&sendTime=&extno=";   //短信请求


        String  contentTemplate = "【soico】 用户 %s 请求提现\n"+
                "原充值地址：%s\n"+
                "现转出地址：%s\n"+
                "转账金额为：%s\n"+
                "点击下面的链接即刻确认本次提现操作\n\n\n"
                +"%s";//短信内容

        Projects projects = new Projects();
        projects.setProject_wallet(addr);
        String hexValue = investmentRecordService.transaction(capital,projects,refundRecord.getAmount().toString());
        String transactionUrl = "https://api.etherscan.io/api?module=proxy&action=eth_sendRawTransaction&hex=%s&apikey=H6T8WITXFCYG189UEFV2FTNAGWZQIFWHQW";
        transactionUrl=  String.format(transactionUrl,hexValue);
        String content =  String.format(contentTemplate,phone,orignalAddr,addr,refundRecord.getAmount(),transactionUrl);
        //短信内容使用URL编码
        try {
            content = URLEncoder.encode(content,"UTF-8");
        } catch (UnsupportedEncodingException e) {
            businessResponse.setCode("-1");
            businessResponse.setMessage("failed");
            businessResponse.setContent("encoder down, please try later!");
            return businessResponse;
        }

        String messargeUrl = String.format(messageTemp,"13850089777",content);
        System.out.println(messargeUrl);
        try {
            response = Unirest.post(messargeUrl)
                    .header("cache-control", "no-cache")
                    .asString();
            String messagePlatformResp = response.getBody();
            Document doc  = DocumentHelper.parseText(messagePlatformResp);
            Element  element = doc.getRootElement();
            Iterator iter = element.elementIterator();
            while (iter.hasNext()) {
                Element recordEle = (Element) iter.next();
                if ("returnstatus".equals(recordEle.getName())){
                    if (!"Success".equals(recordEle.getTextTrim())){
                        businessResponse.setCode("-1");
                        businessResponse.setMessage("failed");
                        businessResponse.setContent("message platform down, please try later!");
                    }else {
                        businessResponse.setCode("0");
                        businessResponse.setMessage("success");
                        businessResponse.setContent("success!");
                    }
                }
            }

        } catch (UnirestException e) {
            businessResponse.setCode("-1");
            businessResponse.setMessage("failed");
            businessResponse.setContent("短信平台拥堵，请稍后再试！");
            return businessResponse;
        } catch (DocumentException e) {
            e.printStackTrace();
            businessResponse.setCode("-1");
            businessResponse.setMessage("failed");
            businessResponse.setContent("短信平台拥堵，请稍后再试！");
            return businessResponse;
        }

//        String txHash = investmentRecordService.withdraw(refundRecord.getAmount().toString(),addr,capital);
//        if (txHash==null){
//            throw new BussinessException("-1","以太坊交易失败，请稍后再试!");
//        }

        businessResponse.setCode("0");
        businessResponse.setMessage("提现申请成功，提现有人工审核过程以及区块写入时间，余额短时间不会变动，请不要重复操作");
//        businessResponse.setContent(txHash);
        return businessResponse;
    }



    /**
     *  查询提现记录
     * @param addr
     * @return
     */
    @RequestMapping(value = "/withdraw/user/{addr}/{userPk}", method = RequestMethod.GET)
    @ResponseBody
    public Object TransactionWithdraw(@PathVariable String addr, @PathVariable Long userPk,@RequestHeader("User") Long user){
        BusinessResponse businessResponse = new BusinessResponse();
        if (user.longValue()!=userPk.longValue()){
            businessResponse.setCode("-1");
            businessResponse.setMessage("无效的请求!");
            return businessResponse;
        }
        businessResponse.setCode("0");
        businessResponse.setMessage("success");
        businessResponse.setContent(capitalService.getTransactionWithdrawRecords(addr,userPk));
        return businessResponse;
    }


}
